﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Tea.Parser {

    /// <summary>
    /// 所有标识符的枚举。
    /// </summary>
    public sealed class Token {

        static Dictionary<TokenType, Token> _values = new Dictionary<TokenType, Token>();
        
        /// <summary>
        /// 根据标识符类型获取详细信息。
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static Token Find(TokenType type) {
            return _values[type];
        }

        public static bool IsSymbol(TokenType type) {
            return type <= TokenType.FalseLiteral;
        }

        /// <summary>
        /// 根据字符串缓存获取标识符类型。
        /// </summary>
        /// <param name="value">缓存。</param>
        /// <returns>返回类型。</returns>
        public static TokenType GetTokenType(StringBuilder value) {
            switch (value.Length) {

                #region 2

                case 2:
                    switch (value[1]) {
                        case 'f':
                            if (value[0] == 'i') return TokenType.If;
                            break;

                        case 'n':
                            if (value[0] == 'i') return TokenType.In;
                            break;

                        case 'o':
                            if (value[0] == 'd') return TokenType.Do;
                            break;

                    }

                    break;

                #endregion

                #region 3

                case 3:
                    switch (value[0]) {

                        case 'f':
                            if (value[1] == 'o' && value[2] == 'r') return TokenType.For;
                            break;

                        //case 'i':
                        //    if (value[1] == 'n' && value[2] == 't') return TokenType.Int;
                        //    break;

                        case 'l':
                            if (value[1] == 'e' && value[2] == 't') return TokenType.Let;
                            break;

                        case 'n':
                            if (value[1] == 'e' && value[2] == 'w') return TokenType.New;
                            break;

                        case 't':
                            if (value[1] == 'r' && value[2] == 'y') return TokenType.Try;
                            break;

                        case 'v':
                            if (value[1] == 'a' && value[2] == 'r') return TokenType.Var;
                            break;

                    }

                    break;

                #endregion

                #region 4

                case 4:


                    switch (value[0]) {
                        //case 'b':
                        //    if (value[1] == 'y' && value[2] == 't' && value[3] == 'e')
                        //        return TokenType.Byte;
                        //    break;

                        case 'c':

                            switch (value[3]) {
                                case 'e':
                                    if (value[2] == 's' && value[1] == 'a')
                                        return TokenType.Case;
                                    break;

                                //case 'r':
                                //    if (value[2] == 's' && value[1] == 'h')
                                //        return TokenType.Char;
                                //    break;

                            }


                            break;
                        case 'e':

                            switch (value[3]) {
                                case 'e':
                                    if (value[2] == 's' && value[1] == 'l')
                                        return TokenType.Else;
                                    break;

                                //case 'm':
                                //    if (value[2] == 'u' && value[1] == 'n')
                                //        return TokenType.Enum;
                                //    break;

                            }

                            break;


                        //case 'g':
                        //    if (value[1] == 'o' && value[2] == 't' && value[3] == 'o')
                        //        return TokenType.Goto;
                        //    break;

                        //case 'l':
                        //    if (value[1] == 'o' && value[2] == 'n' && value[3] == 'g')
                        //        return TokenType.Long;
                        //    break;

                        case 'n':
                            if (value[1] == 'u' && value[2] == 'l' && value[3] == 'l')
                                return TokenType.NullLiteral;
                            break;

                        case 't':

                            switch (value[3]) {
                                case 'e':
                                    if (value[2] == 'u' && value[1] == 'r')
                                        return TokenType.TrueLiteral;
                                    break;

                                case 's':
                                    if (value[2] == 'i' && value[1] == 'h')
                                        return TokenType.This;
                                    break;

                            }

                            break;
                        case 'v':
                            if (value[1] == 'o' && value[2] == 'i' && value[3] == 'd')
                                return TokenType.Void;
                            break;

                        case 'w':

                            if (value[1] == 'i' && value[2] == 't' && value[3] == 'h')
                                return TokenType.With;
                            break;

                    }

                    break;

                #endregion

                #region 5

                case 5:
                    switch (value[2]) {
                        //case 'a':
                        //    if (value[0] == 'c' && value[1] == 'l' && value[3] == 's' && value[4] == 's')
                        //        return TokenType.Class;
                        case 'e':
                            switch (value[0]) {
                                case 'b':
                                    if (value[1] == 'r' && value[3] == 'a' && value[4] == 'k')
                                        return TokenType.Break;

                                    break;

                                case 'y':
                                    if (value[1] == 'i' && value[3] == 'l' && value[4] == 'd')
                                        return TokenType.Yield;

                                    break;
                            }


                            break;
                        case 'i':
                            if (value[0] == 'w' && value[1] == 'h' && value[3] == 'l' && value[4] == 'e')
                                return TokenType.While;

                            break;
                        case 'l': if (value[0] == 'f' && value[1] == 'a' && value[3] == 's' && value[4] == 'e')
                                return TokenType.FalseLiteral;

                            break;
                        case 'n':
                            switch (value[0]) {
                                case 'c':
                                    if (value[1] == 'o' && value[3] == 's' && value[4] == 't')
                                        return TokenType.Const;

                                    break;

                                //case 'f':
                                //    if (value[1] == 'i' && value[3] == 'a' && value[4] == 'l')
                                //        return TokenType.Final;

                                //    break;
                            }


                            break;
                        //case 'o':
                        //    switch (value[0]) {
                        //        case 'f':
                        //            if (value[1] == 'l' && value[3] == 'a' && value[4] == 't')
                        //                return TokenType.Float;

                        //            break;

                        //        case 's':
                        //            if (value[1] == 'h' && value[3] == 'r' && value[4] == 't')
                        //                return TokenType.Short;

                        //            break;
                        //    }


                        //    break;
                        //case 'p':
                        //    if (value[0] == 's' && value[1] == 'u' && value[3] == 'e' && value[4] == 'r')
                        //        return TokenType.Super;
                        //    break;
                        case 'r':
                            if (value[0] == 't' && value[1] == 'h' && value[3] == 'o' && value[4] == 'w')
                                return TokenType.Throw;

                            break;
                        case 't': if (value[0] == 'c' && value[1] == 'a' && value[3] == 'c' && value[4] == 'h')
                                return TokenType.Catch;

                            break;
                    }

                    break;

                #endregion

                #region 6

                case 6:


                    switch (value[1]) {
                        case 'a':
                            
                            if (value[0] == 'n' && value[1] == 't' && value[3] == 'i' && value[4] == 'v' && value[5] == 'e')
                                return TokenType.Native;

                            break;
                        case 'e':
                            switch (value[0]) {
                                case 'd':
                                    if (value[2] == 'l' && value[3] == 'e' && value[4] == 't' && value[5] == 'e')
                                        return TokenType.Delete;

                                    break;

                                case 'r':
                                    if (value[2] == 't' && value[3] == 'u' && value[4] == 'r' && value[5] == 'n')
                                        return TokenType.Return;

                                    break;
                            }

                            break;
                        //case 'h': if (value[2] == 't' && value[3] == 'r' && value[4] == 'o' && value[5] == 'w' && value[1] == 's')
                        //        return TokenType.Throws;

                        //    break;
                        //case 'm':
                        //    if (value[0] == 'i' && value[2] == 'p' && value[3] == 'o' && value[4] == 'r' && value[5] == 't')
                        //        return TokenType.Import;

                        //case 'o':
                        //    if (value[0] == 'd' && value[2] == 'u' && value[3] == 'b' && value[4] == 'l' && value[5] == 'e')
                        //        return TokenType.Double;
                        //    break;

                        //case 't':
                        //    if (value[0] == 's' && value[2] == 'a' && value[3] == 't' && value[4] == 'i' && value[1] == 'c')
                        //        return TokenType.Static;
                        //    break;

                        //case 'u':
                        //    if (value[0] == 'p' && value[2] == 'b' && value[3] == 'l' && value[4] == 'i' && value[1] == 'c')
                        //        return TokenType.Public;
                        //    break;

                        case 'w':
                            if (value[0] == 's' && value[2] == 'i' && value[3] == 't' && value[4] == 'c' && value[5] == 'h')
                                return TokenType.Switch;
                            break;

                        //case 'x':
                        //    if (value[0] == 'e' && value[2] == 'p' && value[3] == 'o' && value[4] == 'r' && value[5] == 't')
                        //        return TokenType.Export;
                        //    break;

                        case 'y':
                            if (value[0] == 't' && value[2] == 'p' && value[3] == 'e' && value[4] == 'o' && value[5] == 'f')
                                return TokenType.Typeof;
                            break;

                    }

                    break;

                #endregion

                #region 7

                case 7:
                    switch (value[1]) {
                        //case 'a':
                        //    if (value[0] == 'p' && value[2] == 'c' && value[3] == 'k' && value[4] == 'a' && value[5] == 'g' && value[6] == 'e')
                        //        return TokenType.Package;
                        //    break;

                        case 'e':
                            if (value[0] == 'd' && value[2] == 'f' && value[3] == 'a' && value[4] == 'u' && value[5] == 'l' && value[6] == 't') return TokenType.Default;
                            break;

                        case 'i':
                            if (value[0] == 'f' && value[2] == 'n' && value[3] == 'a' && value[4] == 'l' && value[5] == 'l' && value[6] == 'y') return TokenType.Finally;
                            break;

                        //case 'o':
                        //    if (value[0] == 'b' && value[2] == 'o' && value[3] == 'l' && value[4] == 'a' && value[5] == 'a' && value[6] == 'n') return TokenType.Boolean;
                        //    break;

                        //case 'r':
                        //    if (value[0] == 'p' && value[2] == 'i' && value[3] == 'v' && value[4] == 'a' && value[5] == 't' && value[6] == 'e') return TokenType.Private;
                        //    break;

                        //case 'x':
                        //    if (value[0] == 'e' && value[2] == 't' && value[3] == 'e' && value[4] == 'n' && value[5] == 'd' && value[6] == 's')
                        //        return TokenType.Extends;
                        //    break;

                    }

                    break;

                #endregion

                #region 8

                case 8:

                    switch (value[0]) {

                        //case 'a':
                        //    if (value[1] == 'b' && value[2] == 's' && value[3] == 't' && value[4] == 'r' && value[5] == 'a' && value[6] == 'c' && value[7] == 't')
                        //        return TokenType.Abstract;
                        //    break;

                        case 'c':
                            if (value[1] == 'o' && value[2] == 'n' && value[3] == 't' && value[4] == 'i' && value[5] == 'n' && value[6] == 'u' && value[7] == 'e')
                                return TokenType.Continue;
                            break;

                        case 'd':
                            if (value[1] == 'e' && value[2] == 'b' && value[3] == 'u' && value[4] == 'g' && value[5] == 'g' && value[6] == 'e' && value[7] == 'r')
                                return TokenType.Debugger;
                            break;

                        case 'f':

                            if (value[1] == 'u' && value[2] == 'n' && value[3] == 'c' && value[4] == 't' && value[5] == 'i' && value[6] == 'o' && value[7] == 'n')
                                return TokenType.Function;
                            break;


                        //case 'v':

                        //    if (value[1] == 'o' && value[2] == 'l' && value[3] == 'a' && value[4] == 't' && value[5] == 'i' && value[6] == 'l' && value[7] == 'e') return TokenType.Volatile;
                        //    break;



                    }

                    break;

                #endregion

                #region 9

                //case 9:

                //    switch (value[0]) {
                //        case 'i':
                //            if (value[1] == 'n' && value[2] == 't' && value[3] == 'e' && value[4] == 'r' && value[5] == 'g' && value[6] == 'a' && value[7] == 'c' && value[8] == 'e')
                //                return TokenType.Interface;
                //            break;

                //        case 'p':
                //            if (value[1] == 'r' && value[2] == 'o' && value[3] == 't' && value[4] == 'e' && value[5] == 'c' && value[6] == 't' && value[7] == 'e' && value[8] == 'd')
                //                return TokenType.Protected;
                //            break;

                //        case 't':
                //            if (value[1] == 'r' && value[2] == 'a' && value[3] == 'n' && value[4] == 's' && value[5] == 'i' && value[6] == 'e' && value[7] == 'n' && value[8] == 't')
                //                return TokenType.Transient;
                //            break;

                //    }
                //    break;

                #endregion

                #region 10

                case 10:

                    if (value[0] == 'i') {
                        switch (value[1]) {
                            //case 'm':
                            //    if (value[2] == 'p' && value[3] == 'l' && value[4] == 'e' && value[5] == 'm' && value[6] == 'e' && value[7] == 'n' && value[8] == 't' && value[9] == 's')
                            //        return TokenType.Implements;

                            case 'n':
                                if (value[2] == 's' && value[3] == 't' && value[4] == 'a' && value[5] == 'n' && value[6] == 'c' && value[7] == 'e' && value[8] == 'o' && value[9] == 'f')
                                    return TokenType.Instanceof;
                                break;


                        }
                    }
                    break;

                #endregion

                #region 12

                //case 12:
                //    if (value[0] == 's' && value[1] == 'y' && value[2] == 'n' && value[3] == 'c' && value[4] == 'h' && value[5] == 'r' && value[6] == 'o' && value[7] == 'n' && value[8] == 'i' && value[9] == 'z' && value[10] == 'e' && value[11] == 'd')

                //        return TokenType.Synchronized;
                //    break;

                #endregion

            }


            return TokenType.Identifier;
        }

        #region 成员

        public readonly string Name;

        public readonly int Priority;

        public TokenType Type {
            get {
                foreach(var key in _values){
                    if(key.Value == this){
                        return key.Key;
                    }
                }

                return TokenType.EOS;
            }
        }

        public Token(TokenType type, string name, int priority) {
            Name = name;
            Priority = priority;

            if (_values.ContainsKey(type)) {
                throw new ArgumentException("已经添加过 type = " + type + " 的操作符");
            }
            _values[type] = this;
        }

        /// <summary>
        /// 返回表示当前 <see cref="T:System.Object"/> 的 <see cref="T:System.String"/>。
        /// </summary>
        /// <returns>
        /// 	<see cref="T:System.String"/>，表示当前的 <see cref="T:System.Object"/>。
        /// </returns>
        public override string ToString() {
            return Name;
        }

        #endregion

        #region 特殊

        /// <summary>
        /// 表示流为空。 (EndOfStream 简写)
        /// </summary>
        public static readonly Token EOS = new Token(TokenType.EOS, "EOS", 0);

        #endregion

        #region 连接

        /// <summary>
        /// (
        /// </summary>
        public static readonly Token LParam = new Token(TokenType.LParam, "(", 0);

        /// <summary>
        /// )
        /// </summary>
        public static readonly Token RParam = new Token(TokenType.RParam, ")", 0);

        /// <summary>
        /// [
        /// </summary>
        public static readonly Token LBrack = new Token(TokenType.LBrack, "[", 0);

        /// <summary>
        /// ]
        /// </summary>
        public static readonly Token RBrack = new Token(TokenType.RBrack, "]", 0);

        /// <summary>
        /// {
        /// </summary>
        public static readonly Token LBrace = new Token(TokenType.LBrace, "{", 0);

        /// <summary>
        /// }
        /// </summary>
        public static readonly Token RBrace = new Token(TokenType.RBrace, "}", 0);

        /// <summary>
        /// :
        /// </summary>
        public static readonly Token Colon = new Token(TokenType.Colon, ":", 0);

        /// <summary>
        /// ;
        /// </summary>
        public static readonly Token Semicolon = new Token(TokenType.Semicolon, ";", 0);

        /// <summary>
        /// .
        /// </summary>
        public static readonly Token Period = new Token(TokenType.Period, ".", 0);

        /// <summary>
        /// ?
        /// </summary>
        public static readonly Token Conditional = new Token(TokenType.Conditional, "?", 3);

        /// <summary>
        /// ++
        /// </summary>
        public static readonly Token Inc = new Token(TokenType.Inc, "++", 0);

        /// <summary>
        /// --
        /// </summary>
        public static readonly Token Dec = new Token(TokenType.Dec, "--", 0);

        #endregion

        #region 赋值

        /// <summary>
        /// init_var
        /// </summary>
        public static readonly Token InitVar = new Token(TokenType.InitVar, "init_var", 2);

        /// <summary>
        /// init_const
        /// </summary>
        public static readonly Token InitConst = new Token(TokenType.InitConst, "init_const", 2) /* AST-use only. */ ;

        /// <summary>
        /// =
        /// </summary>
        public static readonly Token Assign = new Token(TokenType.Assign, "=", 2);

        /// <summary>
        /// !=
        /// </summary>
        public static readonly Token AssignBitOr = new Token(TokenType.AssignBitOr, "|=", 2);

        /// <summary>
        /// ^=
        /// </summary>
        public static readonly Token AssignBitXor = new Token(TokenType.AssignBitXor, "^=", 2);

        /// <summary>
        /// &amp;=
        /// </summary>
        public static readonly Token AssignBitAnd = new Token(TokenType.AssignBitAnd, "&=", 2);

        /// <summary>
        /// &lt;&lt=
        /// </summary>
        public static readonly Token AssignShl = new Token(TokenType.AssignShl, "<<=", 2);

        /// <summary>
        /// &gt;&gt;=
        /// </summary>
        public static readonly Token AssignSar = new Token(TokenType.AssignSar, ">>=", 2);

        /// <summary>
        /// &gt;&gt;&gt;=
        /// </summary>
        public static readonly Token AssignShr = new Token(TokenType.AssignShr, ">>>=", 2);

        /// <summary>
        /// +=
        /// </summary>
        public static readonly Token AssignAdd = new Token(TokenType.AssignAdd, "+=", 2);

        /// <summary>
        /// -=
        /// </summary>
        public static readonly Token AssignSub = new Token(TokenType.AssignSub, "-=", 2);

        /// <summary>
        /// *=
        /// </summary>
        public static readonly Token AssignMul = new Token(TokenType.AssignMul, "*=", 2);

        /// <summary>
        /// /=
        /// </summary>
        public static readonly Token AssignDiv = new Token(TokenType.AssignDiv, "/=", 2);

        /// <summary>
        /// %=
        /// </summary>
        public static readonly Token AssignMod = new Token(TokenType.AssignMod, "%=", 2);


        #endregion

        #region 二进制

        /// <summary>
        /// ,
        /// </summary>
        public static readonly Token Comma = new Token(TokenType.Comma, ",", 1);

        /// <summary>
        /// ||
        /// </summary>
        public static readonly Token Or = new Token(TokenType.Or, "||", 4);

        /// <summary>
        /// &amp;&amp;
        /// </summary>
        public static readonly Token And = new Token(TokenType.And, "&&", 5);

        /// <summary>
        /// |
        /// </summary>
        public static readonly Token BitOr = new Token(TokenType.BitOr, "|", 6);

        /// <summary>
        /// ^
        /// </summary>
        public static readonly Token BitXor = new Token(TokenType.BitXor, "^", 7);

        /// <summary>
        /// &
        /// </summary>
        public static readonly Token BitAnd = new Token(TokenType.BitAnd, "&", 8);

        /// <summary>
        /// &lt;&lt;
        /// </summary>
        public static readonly Token Shl = new Token(TokenType.Shl, "<<", 11);

        /// <summary>
        /// &gt;&gt;
        /// </summary>
        public static readonly Token Sar = new Token(TokenType.Sar, ">>", 11);

        /// <summary>
        /// &gt;&gt;&gt;
        /// </summary>
        public static readonly Token Shr = new Token(TokenType.Shr, ">>>", 11);

        /// <summary>
        /// +
        /// </summary>
        public static readonly Token Add = new Token(TokenType.Add, "+", 12);

        /// <summary>
        /// -
        /// </summary>
        public static readonly Token Sub = new Token(TokenType.Sub, "-", 12);

        /// <summary>
        /// *
        /// </summary>
        public static readonly Token Mul = new Token(TokenType.Mul, "*", 13);

        /// <summary>
        /// /
        /// </summary>
        public static readonly Token Div = new Token(TokenType.Div, "/", 13);

        /// <summary>
        /// %
        /// </summary>
        public static readonly Token Mod = new Token(TokenType.Mod, "%", 13);


        #endregion

        #region 比较

        /// <summary>
        /// =
        /// </summary>
        public static readonly Token Eq = new Token(TokenType.Eq, "=", 9);

        /// <summary>
        /// !=
        /// </summary>
        public static readonly Token Ne = new Token(TokenType.Ne, "!=", 9);

        /// <summary>
        /// ==
        /// </summary>
        public static readonly Token EqStrict = new Token(TokenType.EqStrict, "==", 9);

        /// <summary>
        /// !==
        /// </summary>
        public static readonly Token NeStrict = new Token(TokenType.NeStrict, "!==", 9);

        /// <summary>
        /// &lt;
        /// </summary>
        public static readonly Token Lt = new Token(TokenType.Lt, "<", 10);

        /// <summary>
        /// &gt;
        /// </summary>
        public static readonly Token Gt = new Token(TokenType.Gt, ">", 10);

        /// <summary>
        /// &lt;=
        /// </summary>
        public static readonly Token Lte = new Token(TokenType.Lte, "<=", 10);

        /// <summary>
        /// &gt;=
        /// </summary>
        public static readonly Token Gte = new Token(TokenType.Gte, ">=", 10);

        /// <summary>
        /// instanceof
        /// </summary>
        public static readonly Token Instanceof = new Token(TokenType.Instanceof, "instanceof", 10);

        /// <summary>
        /// in
        /// </summary>
        public static readonly Token In = new Token(TokenType.In, "in", 10);


        #endregion

        #region 单目

        /// <summary>
        /// !
        /// </summary>
        public static readonly Token Not = new Token(TokenType.Not, "!", 0);

        /// <summary>
        /// ~
        /// </summary>
        public static readonly Token BitNot = new Token(TokenType.BitNot, "~", 0);

        /// <summary>
        /// delete
        /// </summary>
        public static readonly Token Delete = new Token(TokenType.Delete, "delete", 0);

        /// <summary>
        /// typeof
        /// </summary>
        public static readonly Token Typeof = new Token(TokenType.Typeof, "typeof", 0);

        /// <summary>
        /// void
        /// </summary>
        public static readonly Token Void = new Token(TokenType.Void, "void", 0);


        #endregion

        #region 关键字

        /// <summary>
        /// break
        /// </summary>
        public static readonly Token Break = new Token(TokenType.Break, "break", 0);

        /// <summary>
        /// case
        /// </summary>
        public static readonly Token Case = new Token(TokenType.Case, "case", 0);

        /// <summary>
        /// catch
        /// </summary>
        public static readonly Token Catch = new Token(TokenType.Catch, "catch", 0);

        /// <summary>
        /// continue
        /// </summary>
        public static readonly Token Continue = new Token(TokenType.Continue, "continue", 0);

        /// <summary>
        /// debugger
        /// </summary>
        public static readonly Token Debugger = new Token(TokenType.Debugger, "debugger", 0);

        /// <summary>
        /// default
        /// </summary>
        public static readonly Token Default = new Token(TokenType.Default, "default", 0);
 
        /* DELETE */

        /// <summary>
        /// do
        /// </summary>
        public static readonly Token Do = new Token(TokenType.Do, "do", 0);

        /// <summary>
        /// else
        /// </summary>
        public static readonly Token Else = new Token(TokenType.Else, "else", 0);

        /// <summary>
        /// finally
        /// </summary>
        public static readonly Token Finally = new Token(TokenType.Finally, "finally", 0);

        /// <summary>
        /// for
        /// </summary>
        public static readonly Token For = new Token(TokenType.For, "for", 0);

        /// <summary>
        /// function
        /// </summary>
        public static readonly Token Function = new Token(TokenType.Function, "function", 0);

        /// <summary>
        /// if
        /// </summary>
        public static readonly Token If = new Token(TokenType.If, "if", 0);
 
        /* IN */ 

        /* INSTANCEOF */

        /// <summary>
        /// new
        /// </summary>
        public static readonly Token New = new Token(TokenType.New, "new", 0);

        /// <summary>
        /// return
        /// </summary>
        public static readonly Token Return = new Token(TokenType.Return, "return", 0);

        /// <summary>
        /// switch
        /// </summary>
        public static readonly Token Switch = new Token(TokenType.Switch, "switch", 0);

        /// <summary>
        /// this
        /// </summary>
        public static readonly Token This = new Token(TokenType.This, "this", 0);

        /// <summary>
        /// throw
        /// </summary>
        public static readonly Token Throw = new Token(TokenType.Throw, "throw", 0);

        /// <summary>
        /// try
        /// </summary>
        public static readonly Token Try = new Token(TokenType.Try, "try", 0);
 
        /* TYPEOF */

        /// <summary>
        /// var
        /// </summary>
        public static readonly Token Var = new Token(TokenType.Var, "var", 0);
 
        /* VOID */

        /// <summary>
        /// while
        /// </summary>
        public static readonly Token While = new Token(TokenType.While, "while", 0);

        /// <summary>
        /// with
        /// </summary>
        public static readonly Token With = new Token(TokenType.With, "with", 0);


        #endregion

        #region 常量 

        /// <summary>
        /// null
        /// </summary>
        public static readonly Token Null = new Token(TokenType.NullLiteral, "null", 0);

        /// <summary>
        /// true
        /// </summary>
        public static readonly Token True = new Token(TokenType.TrueLiteral, "true", 0);

        /// <summary>
        /// false
        /// </summary>
        public static readonly Token False = new Token(TokenType.FalseLiteral, "false", 0);

        /// <summary>
        /// 数字。
        /// </summary>
        public static readonly Token Number = new Token(TokenType.NumberLiteral, null, 0);

        /// <summary>
        /// 字符串。
        /// </summary>
        public static readonly Token String = new Token(TokenType.StringLiteral, null, 0);

        #endregion

        #region 标识符 (非关键词 非未来关键词) 

        /// <summary>
        /// 标识符。
        /// </summary>
        public static readonly Token Identifier = new Token(TokenType.Identifier, Messages.Identifier, 0);

        #endregion

        #region 未来关键词 

        /// <summary>
        /// 未来关键字。
        /// </summary>
        public static readonly Token FutureReservedWord = new Token(TokenType.FutureReservedWord, null, 0);

        /// <summary>
        /// const。
        /// </summary>
        public static readonly Token Const = new Token(TokenType.Const, "const", 0);

        /// <summary>
        /// native。
        /// </summary>
        public static readonly Token Native = new Token(TokenType.Native, "native", 0);


        #endregion

        #region 系统 

        /// <summary>
        /// 非法。
        /// </summary>
        public static readonly Token Illegal = new Token(TokenType.Illegal, "ILLEGAL", 0);

        /// <summary>
        /// 空白。
        /// </summary>
        public static readonly Token Whitespace = new Token(TokenType.Whitespace, null, 0);

        #endregion

    }

    /// <summary>
    /// 代表标识符类型。
    /// </summary>
    public enum TokenType {

        #region 特殊

        /// <summary>
        /// 表示流为空。 (EndOfStream 简写)
        /// </summary>
        EOS,

        #endregion

        #region 连接

        /// <summary>
        /// (
        /// </summary>
        LParam,

        /// <summary>
        /// )
        /// </summary>
        RParam,

        /// <summary>
        /// [
        /// </summary>
        LBrack,

        /// <summary>
        /// ]
        /// </summary>
        RBrack,

        /// <summary>
        /// {
        /// </summary>
        LBrace,

        /// <summary>
        /// }
        /// </summary>
        RBrace,

        /// <summary>
        /// :
        /// </summary>
        Colon,

        /// <summary>
        /// ;
        /// </summary>
        Semicolon,

        /// <summary>
        /// .
        /// </summary>
        Period,

        /// <summary>
        /// ?
        /// </summary>
        Conditional,

        /// <summary>
        /// ++
        /// </summary>
        Inc,

        /// <summary>
        /// --
        /// </summary>
        Dec,

        #endregion

        #region 赋值

        /// <summary>
        /// init_var
        /// </summary>
        InitVar,

        /// <summary>
        /// init_const
        /// </summary>
        InitConst,

        /// <summary>
        /// =
        /// </summary>
        Assign,

        /// <summary>
        /// |=
        /// </summary>
        AssignBitOr,

        /// <summary>
        /// ^=
        /// </summary>
        AssignBitXor,

        /// <summary>
        /// &amp;=
        /// </summary>
        AssignBitAnd,

        /// <summary>
        /// &lt;&lt;=
        /// </summary>
        AssignShl,

        /// <summary>
        /// &gt;&gt;=
        /// </summary>
        AssignSar,

        /// <summary>
        /// &gt;&gt;&gt;=
        /// </summary>
        AssignShr,

        /// <summary>
        /// +=
        /// </summary>
        AssignAdd,

        /// <summary>
        /// -=
        /// </summary>
        AssignSub,

        /// <summary>
        /// *=
        /// </summary>
        AssignMul,

        /// <summary>
        /// /=
        /// </summary>
        AssignDiv,

        /// <summary>
        /// %=
        /// </summary>
        AssignMod,


        #endregion

        #region 二进制

        /// <summary>
        /// ,
        /// </summary>
        Comma,

        /// <summary>
        /// ||
        /// </summary>
        Or,

        /// <summary>
        /// &amp;&amp;
        /// </summary>
        And,

        /// <summary>
        /// |
        /// </summary>
        BitOr,

        /// <summary>
        /// ^
        /// </summary>
        BitXor,

        /// <summary>
        /// &amp;
        /// </summary>
        BitAnd,

        /// <summary>
        /// &lt;&lt;
        /// </summary>
        Shl,

        /// <summary>
        /// &gt;&gt;
        /// </summary>
        Sar,

        /// <summary>
        /// &gt;&gt;&gt;
        /// </summary>
        Shr,

        /// <summary>
        /// +
        /// </summary>
        Add,

        /// <summary>
        /// -
        /// </summary>
        Sub,

        /// <summary>
        /// *
        /// </summary>
        Mul,

        /// <summary>
        /// /
        /// </summary>
        Div,

        /// <summary>
        /// %
        /// </summary>
        Mod,


        #endregion

        #region 比较

        /// <summary>
        /// ==
        /// </summary>
        Eq,

        /// <summary>
        /// !=
        /// </summary>
        Ne,

        /// <summary>
        /// ===
        /// </summary>
        EqStrict,

        /// <summary>
        /// !===
        /// </summary>
        NeStrict,

        /// <summary>
        /// &lt;
        /// </summary>
        Lt,

        /// <summary>
        /// &gt;
        /// </summary>
        Gt,

        /// <summary>
        /// &lt;=
        /// </summary>
        Lte,

        /// <summary>
        /// &gt;=
        /// </summary>
        Gte,

        /// <summary>
        /// instanceof
        /// </summary>
        Instanceof,

        /// <summary>
        /// in
        /// </summary>
        In,


        #endregion

        #region 单目

        /// <summary>
        /// !
        /// </summary>
        Not,

        /// <summary>
        /// ~
        /// </summary>
        BitNot,

        /// <summary>
        /// delete
        /// </summary>
        Delete,

        /// <summary>
        /// typeof
        /// </summary>
        Typeof,

        /// <summary>
        /// void
        /// </summary>
        Void,


        #endregion

        #region 关键字

        /// <summary>
        /// break
        /// </summary>
        Break,

        /// <summary>
        /// case
        /// </summary>
        Case,

        /// <summary>
        /// catch
        /// </summary>
        Catch,

        /// <summary>
        /// continue
        /// </summary>
        Continue,

        /// <summary>
        /// debugger
        /// </summary>
        Debugger,

        /// <summary>
        /// default
        /// </summary>
        Default,

        /* DELETE */

        /// <summary>
        /// do
        /// </summary>
        Do,

        /// <summary>
        /// else
        /// </summary>
        Else,

        /// <summary>
        /// finally
        /// </summary>
        Finally,

        /// <summary>
        /// for
        /// </summary>
        For,

        /// <summary>
        /// function
        /// </summary>
        Function,

        /// <summary>
        /// if
        /// </summary>
        If,

        /* IN */

        /* INSTANCEOF */

        /// <summary>
        /// new
        /// </summary>
        New,

        /// <summary>
        /// return
        /// </summary>
        Return,

        /// <summary>
        /// switch
        /// </summary>
        Switch,

        /// <summary>
        /// this
        /// </summary>
        This,

        /// <summary>
        /// throw
        /// </summary>
        Throw,

        /// <summary>
        /// try
        /// </summary>
        Try,

        /* TYPEOF */

        /// <summary>
        /// var
        /// </summary>
        Var,

        /* VOID */

        /// <summary>
        /// while
        /// </summary>
        While,

        /// <summary>
        /// with
        /// </summary>
        With,


        #endregion

        #region 未来关键词

        /// <summary>
        /// 未来关键字。
        /// </summary>
        FutureReservedWord,

        /// <summary>
        /// const。
        /// </summary>
        Const,

        /// <summary>
        /// native。
        /// </summary>
        Native,

        /// <summary>
        /// yield
        /// </summary>
        Yield,

        /// <summary>
        /// let
        /// </summary>
        Let,

        #endregion

        #region 常量

        /// <summary>
        /// null
        /// </summary>
        NullLiteral,

        /// <summary>
        /// true
        /// </summary>
        TrueLiteral,

        /// <summary>
        /// false
        /// </summary>
        FalseLiteral,

        /// <summary>
        /// 数字。
        /// </summary>
        NumberLiteral,

        /// <summary>
        /// 十进制数字。
        /// </summary>
        DecimalLiteral,

        /// <summary>
        /// 十六进制数字。
        /// </summary>
        HexIntegerLiteral,

        /// <summary>
        /// 八进制数字。
        /// </summary>
        OctalIntegerLiteral,

        /// <summary>
        /// 字符串。
        /// </summary>
        StringLiteral,

        /// <summary>
        /// 字符。
        /// </summary>
        CharLiteral,

        #endregion

        #region 标识符 (非关键词 非未来关键词)

        /// <summary>
        /// 标识符。
        /// </summary>
        Identifier,

        #endregion

        #region 系统

        Target,

        Loop,

        LocalBlock,

        Block,

        Label,

        IfNe,

        /// <summary>
        /// 非法。
        /// </summary>
        Illegal,

        /// <summary>
        /// 空白。
        /// </summary>
        Whitespace,

        /// <summary>
        /// //
        /// </summary>
        SingleLineComment,

        /// <summary>
        /// /*
        /// </summary>
        MultiLineComment,

        /// <summary>
        /// @
        /// </summary>
        At,

        #endregion
    }

    /// <summary>
    /// 表示一个标识符信息。
    /// </summary>
    public sealed class TokenInfo {

        /// <summary>
        /// 表示标识符的类型。
        /// </summary>
        public TokenType Type;

        /// <summary>
        /// 表示当前标识符的开始位置。
        /// </summary>
        public Location StartLocation;

        /// <summary>
        /// 表示当前标识符的结束位置。
        /// </summary>
        public Location EndLocation;

        /// <summary>
        /// 表示当前标识符的字符串缓存。
        /// </summary>
        public StringBuilder LiteralBuffer = new StringBuilder();

        /// <summary>
        /// 获取当前标识符的字符串形式。
        /// </summary>
        public string Literal {
            get {
                return LiteralBuffer.ToString();
            }
        }

        /// <summary>
        /// 返回表示当前 <see cref="T:System.Object"/> 的 <see cref="T:System.String"/>。
        /// </summary>
        /// <returns>
        /// 	<see cref="T:System.String"/>，表示当前的 <see cref="T:System.Object"/>。
        /// </returns>
        public override string ToString() {
            return String.Format("{0}({1} - {2}) {3}", Type, StartLocation, EndLocation, Type >= TokenType.LParam && Type <= TokenType.BitNot ? Token.Find(Type).Name : Literal);
        }

    }
}
